package com.hzy.pms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.hzy.cms.domain.OssInfo;
import com.hzy.pms.domain.Product;
import com.hzy.pms.domain.bo.ProductBo;
import com.hzy.pms.domain.vo.ProductVo;
import com.hzy.pms.mapper.ProductMapper;
import com.ruoyi.common.core.domain.TreeEntity;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.hzy.pms.domain.bo.ProductCategoryBo;
import com.hzy.pms.domain.vo.ProductCategoryVo;
import com.hzy.pms.domain.ProductCategory;
import com.hzy.pms.mapper.ProductCategoryMapper;
import com.hzy.pms.service.IProductCategoryService;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 *
 * @author zengxin
 * @date 2023-10-17
 */
@RequiredArgsConstructor
@Service
public class ProductCategoryServiceImpl implements IProductCategoryService {

    private final ProductCategoryMapper baseMapper;

    private final ProductMapper productMapper;

    /**
     * 查询商品分类
     */
    @Override
    public ProductCategoryVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }


    /**
     * 查询商品分类列表
     */
    @Override
    public List<ProductCategoryVo> queryList(ProductCategoryBo bo) {
        LambdaQueryWrapper<ProductCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ProductCategory> buildQueryWrapper(ProductCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, ProductCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), ProductCategory::getName, bo.getName());
        lqw.eq(bo.getLevel() != null, ProductCategory::getLevel, bo.getLevel());
        lqw.eq(bo.getShowStatus() != null, ProductCategory::getShowStatus, bo.getShowStatus());
        lqw.eq(bo.getSort() != null, ProductCategory::getSort, bo.getSort());
        lqw.eq(StringUtils.isNotBlank(bo.getIcon()), ProductCategory::getIcon, bo.getIcon());
        lqw.orderByAsc(ProductCategory::getSort);
        return lqw;
    }

    /**
     * 新增商品分类
     */
    @Override
    public Boolean insertByBo(ProductCategoryBo bo) {
        ProductCategory add = BeanUtil.toBean(bo, ProductCategory.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改商品分类
     */
    @Override
    public Boolean updateByBo(ProductCategoryBo bo) {
        ProductCategory update = BeanUtil.toBean(bo, ProductCategory.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ProductCategory entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商品分类
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            Assert.isTrue(!this.baseMapper.exists(new LambdaQueryWrapper<ProductCategory>().in(TreeEntity::getParentId, ids)), "存在子分类,不允许删除");
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<ProductCategoryVo> queryCategoryWithProductsForH5() {
        QueryWrapper<ProductCategory> qw1 = new QueryWrapper<>();
//        qw1.eq("level", 0);
        qw1.eq("show_status", 1);
        Page<ProductCategory> pageReq = new Page<>();
        pageReq.setCurrent(1L)
                .setSize(10)
                .setOrders(Collections.singletonList(OrderItem.desc("sort")));
        List<ProductCategoryVo> categories = baseMapper.selectVoPage(pageReq, qw1).getRecords();
        if (CollUtil.isEmpty(categories)) {
            return Collections.emptyList();
        }
        return categories.stream().map(it -> {
            // 寻找该分类下的所有子类
            List<Long> allChildCate = queryAllChildCate(Collections.singletonList(it.getId()), 0);
            QueryWrapper<Product> qw = new QueryWrapper<>();
            qw.select("id", "pic", "name", "price", "category_id");
            qw.in("category_id", allChildCate);
            qw.le("sort", 100);
            List<ProductVo> categoryId2List = productMapper.selectVoList(qw);
            it.setProductList(categoryId2List);
            return it;
        }).collect(Collectors.toList());
    }

    private List<Long> queryAllChildCate(List<Long> categoryIds, int level) {
        List<Long> res = new ArrayList<>();
        QueryWrapper<ProductCategory> qw = new QueryWrapper<>();
        qw.select("id");
        List<Long> ids = categoryIds;
        while (true) {
            qw.clear();
            qw.in("parent_id", ids);
            qw.eq("level", level + 1);
            qw.eq("show_status", 1);
            ids = baseMapper.selectList(qw).stream().map(ProductCategory::getId).collect(Collectors.toList());
            if (CollUtil.isEmpty(ids)) {
                break;
            }
            res.addAll(ids);
            level++;
        }
        res.addAll(categoryIds);
        return res;
    }

    @Override
    public List<ProductCategoryVo> queryWebList(ProductCategoryBo bo) {
        MPJLambdaWrapper<ProductCategory> lqw = buildMPJLambdaWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private MPJLambdaWrapper<ProductCategory> buildMPJLambdaWrapper(ProductCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        MPJLambdaWrapper lqw = new MPJLambdaWrapper<ProductCategory>()
                .select(ProductCategory::getId, ProductCategory::getName, ProductCategory::getParentId, ProductCategory::getLevel)
                .select(OssInfo::getUrl)
                .selectAs(OssInfo::getUrl, ProductCategory::getIcon)
                .leftJoin(OssInfo.class, OssInfo::getOssId, ProductCategory::getIcon)
                .eq(bo.getParentId() != null, ProductCategory::getParentId, bo.getParentId())
                .like(StringUtils.isNotBlank(bo.getName()), ProductCategory::getName, bo.getName())
                .eq(bo.getLevel() != null, ProductCategory::getLevel, bo.getLevel())
                .eq(bo.getShowStatus() != null, ProductCategory::getShowStatus, bo.getShowStatus())
                .eq(bo.getSort() != null, ProductCategory::getSort, bo.getSort())
                .eq(StringUtils.isNotBlank(bo.getIcon()), ProductCategory::getIcon, bo.getIcon())
                .orderByAsc(ProductCategory::getSort);
        return lqw;
    }
}
